/**
    ATClab - scriptable Air Traffic Control simulations.
    Copyright (C) 2010 openatclab@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/


#ifndef __ATC_AIRCRAFTSPRITE_HDR__
#define __ATC_AIRCRAFTSPRITE_HDR__


#ifdef WIN32
	#pragma warning( disable:4786 )
#endif

#include <qobject.h>
#include "atc_types.h"
#include <qcolor.h>
#include <functional>
#include <vector>


//
// Qt classes
//
class Q3Canvas;
class Q3CanvasEllipse;
class Q3CanvasItem;
class Q3CanvasLine;
class Q3CanvasText;
class QPoint;
class QTimer;


namespace atc{


	//
	// atc class declarations
	//

	class  AircraftAgent;
	class  AircraftHistory;
	class  AircraftPath;
	struct AircraftPathToken;

	class  ACLocator;
	class  ACCallOut;
	class  ACDataBlk;
	class  ACCallBlk;
	class  ACAltBlk;
	class  ACVelBlk;

	class  ACHistoryTool;
	class  ACProbeTool;
	class  ACRouteTool;

	class  Canvas;
	class  HistoryTool;
	class  ProbeTool;
	class  RouteTool;


	//
	// 
	//

	enum ActionType { 
			TOGGLE_ROUTE_TOOL
		  , TOGGLE_PROBE_TOOL
		  , TOGGLE_HISTORY_TOOL
	};


	/*!
	 * \class atc::AircraftSprite atc_aircraftsprite.h
	 */
	class AircraftSprite : public QObject {
		Q_OBJECT

	public:
		AircraftSprite( Canvas *, AircraftAgent * );
		~AircraftSprite();

	public: // mutator interface
		void set_data( const char * );
		void set_call( const char * );
		void set_alt( double, double );
//		void set_alt( double );
//		void set_cfl( double );
		void set_vel( double );

		void move_to( double, double );
		void set_colour( const QColor & );
		void set_visible( bool );
		void set_flash( bool );

		void rotate_callout();
		void toggle_route();
		void toggle_history();
		void toggle_probe();

		void vector( double, double );

		void accept();
		void handoff();

	public:
		Canvas*        canvas() { return _canvas; }	// @todo:
		AircraftAgent* agent()  { return _aircraft; }

		double cx() const;
		double cy() const;

		double v() const;
		double a() const;

		const AircraftPath & path() const;
		const AircraftHistory & history() const;

		bool locator_selected( const QPoint & ) const;

		void reroute( const AircraftPathToken *, const Point & );

	public slots:

		void update();
		void invalidate() { _update = true; }
		void next_waypoint();
		void destroy();

	private: // initialize
		void create_locator( );
		void create_callout( );
		void create_textblk( );
		void init_textblk( Q3CanvasText *, int , int );
		void create_vector( );
		void build_outline( Q3Canvas * );
		void add2sprite( Q3CanvasItem * );

		QColor color_lookup() const;
		bool   flash_lookup() const;

		void decode_altblk( double &, double & );

		Point convert2canvas( const double, const double ) const;

	private slots:
		void blink();

	signals:
		void event_recorded( KeyValues & );

	private:
		AircraftAgent  *_aircraft;

		Canvas         *_canvas;
		
		std::vector< Q3CanvasItem * > _sprite;
		
		ACLocator *_locator;
		ACCallOut *_callout;
		ACDataBlk *_datablk;
		ACCallBlk *_callblk;
		ACAltBlk  *_altblk;
		ACVelBlk  *_velblk;

		ACProbeTool    *_velvector;
		ACHistoryTool  *_history;
		ACRouteTool    *_route;


		double  _x, _y;		// canvas location
		bool    _update;
		bool    _visible;
		QColor  _colour;

		QTimer *_flash_timer;
		bool    _blinkon;

	private: // functors

		//
		// MoveBy
		//
		class MoveBy : public std::unary_function< Q3CanvasItem *, void > {
		public:
			MoveBy( const std::pair< double, double > pt )
				: _dx( pt.first ), _dy( pt.second ) {}; 
			MoveBy( const double dx, const double dy ) 
				  : _dx( dx ), _dy( dy ) {};
			void operator ()( Q3CanvasItem * ) const;
		private:
			const double _dx, _dy;
		};

		//
		// SetColour
		//
		class SetColour : public std::unary_function< Q3CanvasItem *, void > {
		public:
			SetColour( const QColor &paint ) 
				: _colour( paint ) {};
			void operator ()( Q3CanvasItem * ) const;
		private:
			const QColor &_colour;
		};

		//
		// SetVisible
		//
		class SetVisible : public std::unary_function< Q3CanvasItem *, void > {
		public:
			SetVisible( const bool status ) 
				: _status( status ) {};
			void operator ()( Q3CanvasItem * ) const;
		private:
			const bool _status;
		};

	};

};

#endif
